package com.miplus.ccrm.workflow.config;


import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.miplus.ccrm.common.EnumRCode;
import com.miplus.ccrm.common.R;
import com.miplus.ccrm.common.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.TypeException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;

@RestControllerAdvice(basePackages = "com.miplus.ccrm")
@Slf4j
public class ExceptionAdvice {
    /**
     * {@code @PathVariable} 和 {@code @RequestParam} 参数校验不通过时抛出的异常处理
     */
    @ExceptionHandler({ConstraintViolationException.class})
    public R<?> handleConstraintViolationException(ConstraintViolationException ex) {
        log.error("ConstraintViolationException", ex);
        return R.Error(EnumRCode.ArgErr, ex.getMessage());
    }

    /**
     * 参数类型不通过时抛出的异常处理
     */
    @ExceptionHandler({TypeException.class})
    public R<?> handleTypeException(TypeException ex) {
        log.warn("TypeException", ex);
        return R.Error(EnumRCode.ArgErr, ex.getMessage());
    }

    /**
     * 参数校验不通过时抛出的异常处理
     */
    @ExceptionHandler({BindException.class})
    public R<?> handleBindException(BindException ex) {
        log.warn("BindException", ex);
        return R.Error(EnumRCode.ArgErr, ex.getMessage());
    }

    /**
     * 参数输入错误，比如整型数输入太长16位之类的HttpMessageNotReadableException
     */
    @ExceptionHandler({InvalidFormatException.class})
    public R<?> handleInvalidFormatException(InvalidFormatException ex) {
        log.warn("InvalidFormatException", ex);
        return R.Error(EnumRCode.ArgErr, ex.getMessage());
    }

    /**
     * 参数输入错误，比如整型数输入太长16位之类的
     */
    @ExceptionHandler({HttpMessageNotReadableException.class})
    public R<?> handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) {
        log.warn("HttpMessageNotReadableException:{}", ex.getMessage());
        return R.Error(EnumRCode.ArgErr, ex.getMessage());
    }

    /**
     * OpenFeign调用失败，比如服务名找不到
     */
    /*@ExceptionHandler({FeignException.class})
    public R<?> handleFeignException(FeignException ex) {
        log.warn("FeignException:{}",ex.getMessage());
        return R.Error(EnumRCode.FeignErr, ex.getMessage());
    }
    */
    @ExceptionHandler({ServiceException.class})
    public R<?> handle(ServiceException ex) {
        log.warn("ServiceException:code={},message={}", ex.getCode(), ex.getMessage());
        return R.Error(ex.getCode(), ex.getMessage());
    }

    @ExceptionHandler({RuntimeException.class})
    public R<?> handle(RuntimeException ex) {
        log.error("RuntimeException", ex);
        return R.Error(EnumRCode.RuntimeException, ex.getMessage());
    }

    /**
     * 顶级异常捕获并统一处理，当其他异常无法处理时候选择使用
     */
    @ExceptionHandler({Exception.class})
    public R<?> handle(Exception ex) {
        log.error("TopException", ex);
        return R.Error(EnumRCode.Exception, ex.getMessage());
    }
}